-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[runtimes][PAC] Harden unwinding when possible #143230
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-pgo @llvm/pr-subscribers-libunwind Author: Oliver Hunt (ojhunt) ChangesThis hardens the unwinding logic and datastructures on systems that support pointer authentication. The approach taken to hardening is to harden the schemas of as many high value fields in the myriad structs as possible, and then also explicitly qualify local variables referencing privileged or security critical values. This ABI is exposed to the personality functions, and so updating to conform to that is a mandatory change, but to reduce the risk of oracles, the adoption also hardened the locals and datastructures in compiler-rt and libcxxabi. We're gating these on Patch is 51.36 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/143230.diff 14 Files Affected:
diff --git a/compiler-rt/lib/builtins/gcc_personality_v0.c b/compiler-rt/lib/builtins/gcc_personality_v0.c
index ef63a5fb83472..42b992949d2cc 100644
--- a/compiler-rt/lib/builtins/gcc_personality_v0.c
+++ b/compiler-rt/lib/builtins/gcc_personality_v0.c
@@ -30,6 +30,45 @@ EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, void *, PCONTEXT,
_Unwind_Personality_Fn);
#endif
+#if __has_include(<ptrauth.h>)
+#include <ptrauth.h>
+#endif
+
+#if defined(__APPLE__) && __has_feature(ptrauth_qualifier)
+#if __has_feature(ptrauth_restricted_intptr_qualifier)
+#define PERSONALITY_PTRAUTH_RESTRICTED_INTPTR(key, addressDiscriminated, \
+ discriminatorString) \
+ __ptrauth_restricted_intptr(key, addressDiscriminated, \
+ ptrauth_string_discriminator(discriminatorString))
+#else
+#define PERSONALITY_PTRAUTH_RESTRICTED_INTPTR(key, addressDiscriminated, \
+ discriminatorString) \
+ __ptrauth(key, addressDiscriminated, \
+ ptrauth_string_discriminator(discriminatorString))
+#endif
+#else
+#define PERSONALITY_PTRAUTH_RESTRICTED_INTPTR(key, addressDiscriminated, \
+ discriminatorString)
+#endif
+
+// Helper wrappers for pointer auth qualifiers because we use a lot of variants
+// Suffixes:
+// * PDC : ptrauth_key_process_dependent_code
+// * RA : ptrauth_key_return_address
+// * FN : ptrauth_key_function_pointer
+#define PERSONALITY_PTRAUTH_RI_FN(__discriminator) \
+ PERSONALITY_PTRAUTH_RESTRICTED_INTPTR(ptrauth_key_function_pointer, \
+ /*__address_discriminated=*/1, \
+ __discriminator)
+#define PERSONALITY_PTRAUTH_RI_PDC(__discriminator) \
+ PERSONALITY_PTRAUTH_RESTRICTED_INTPTR(ptrauth_key_process_dependent_code, \
+ /*__address_discriminated=*/1, \
+ __discriminator)
+#define PERSONALITY_PTRAUTH_RI_RA(__discriminator) \
+ PERSONALITY_PTRAUTH_RESTRICTED_INTPTR(ptrauth_key_return_address, \
+ /*__address_discriminated=*/1, \
+ __discriminator)
+
// Pointer encodings documented at:
// http://refspecs.freestandards.org/LSB_1.3.0/gLSB/gLSB/ehframehdr.html
@@ -205,7 +244,8 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0(
return continueUnwind(exceptionObject, context);
uintptr_t pc = (uintptr_t)_Unwind_GetIP(context) - 1;
- uintptr_t funcStart = (uintptr_t)_Unwind_GetRegionStart(context);
+ uintptr_t PERSONALITY_PTRAUTH_RI_FN("__gcc_personality_v0'funcStart")
+ funcStart = (uintptr_t)_Unwind_GetRegionStart(context);
uintptr_t pcOffset = pc - funcStart;
// Parse LSDA header.
@@ -224,11 +264,14 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0(
const uint8_t *callSiteTableEnd = callSiteTableStart + callSiteTableLength;
const uint8_t *p = callSiteTableStart;
while (p < callSiteTableEnd) {
- uintptr_t start = readEncodedPointer(&p, callSiteEncoding);
- size_t length = readEncodedPointer(&p, callSiteEncoding);
- size_t landingPad = readEncodedPointer(&p, callSiteEncoding);
+ uintptr_t PERSONALITY_PTRAUTH_RI_PDC("__gcc_personality_v0'start")
+ start = readEncodedPointer(&p, callSiteEncoding);
+ size_t PERSONALITY_PTRAUTH_RI_PDC("__gcc_personality_v0'length")
+ length = readEncodedPointer(&p, callSiteEncoding);
+ size_t PERSONALITY_PTRAUTH_RI_PDC("__gcc_personality_v0'landingPadOffset")
+ landingPadOffset = readEncodedPointer(&p, callSiteEncoding);
readULEB128(&p); // action value not used for C code
- if (landingPad == 0)
+ if (landingPadOffset == 0)
continue; // no landing pad for this entry
if ((start <= pcOffset) && (pcOffset < (start + length))) {
// Found landing pad for the PC.
@@ -238,7 +281,21 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0(
_Unwind_SetGR(context, __builtin_eh_return_data_regno(0),
(uintptr_t)exceptionObject);
_Unwind_SetGR(context, __builtin_eh_return_data_regno(1), 0);
- _Unwind_SetIP(context, (funcStart + landingPad));
+#define LANDING_PAD_DISCRIMINATOR "__gcc_personality_v0'landingPad"
+ size_t PERSONALITY_PTRAUTH_RI_RA(LANDING_PAD_DISCRIMINATOR)
+ landingPad = funcStart + landingPadOffset;
+#if defined(__APPLE__) && __has_feature(ptrauth_qualifier)
+ uintptr_t stack_pointer = _Unwind_GetGR(context, -2);
+ const uintptr_t existingDiscriminator = ptrauth_blend_discriminator(
+ &landingPad,
+ ptrauth_string_discriminator(LANDING_PAD_DISCRIMINATOR));
+ uintptr_t newIP = (uintptr_t)ptrauth_auth_and_resign(
+ *(void **)&landingPad, ptrauth_key_function_pointer,
+ existingDiscriminator, ptrauth_key_return_address, stack_pointer);
+ _Unwind_SetIP(context, newIP);
+#else
+ _Unwind_SetIP(context, landingPad);
+#endif
return _URC_INSTALL_CONTEXT;
}
}
diff --git a/compiler-rt/lib/profile/InstrProfilingValue.c b/compiler-rt/lib/profile/InstrProfilingValue.c
index a608d41d39e77..cd6ae3d7a4248 100644
--- a/compiler-rt/lib/profile/InstrProfilingValue.c
+++ b/compiler-rt/lib/profile/InstrProfilingValue.c
@@ -83,7 +83,13 @@ __llvm_profile_iterate_data(const __llvm_profile_data *Data) {
/* This method is only used in value profiler mock testing. */
COMPILER_RT_VISIBILITY void *
__llvm_get_function_addr(const __llvm_profile_data *Data) {
- return Data->FunctionPointer;
+ void *FP = Data->FunctionPointer;
+#if __has_feature(ptrauth_calls)
+ // This is only used for tests where we compare against what happens to be
+ // signed pointers.
+ FP = ptrauth_sign_unauthenticated(FP, VALID_CODE_KEY, 0);
+#endif
+ return FP;
}
/* Allocate an array that holds the pointers to the linked lists of
diff --git a/libcxxabi/include/__cxxabi_config.h b/libcxxabi/include/__cxxabi_config.h
index 759445dac91f9..e67d065fe57f3 100644
--- a/libcxxabi/include/__cxxabi_config.h
+++ b/libcxxabi/include/__cxxabi_config.h
@@ -32,7 +32,8 @@
#endif
#if defined(_WIN32)
- #if defined(_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS) || (defined(__MINGW32__) && !defined(_LIBCXXABI_BUILDING_LIBRARY))
+ #if defined(_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS) || \
+ (defined(__MINGW32__) && !defined(_LIBCXXABI_BUILDING_LIBRARY))
#define _LIBCXXABI_HIDDEN
#define _LIBCXXABI_DATA_VIS
#define _LIBCXXABI_FUNC_VIS
@@ -109,4 +110,49 @@
# define _LIBCXXABI_NOEXCEPT noexcept
#endif
+#if __has_include(<ptrauth.h>)
+#include <ptrauth.h>
+#endif
+
+#if defined(__APPLE__) && __has_feature(ptrauth_qualifier)
+# define _LIBCXXABI_PTRAUTH(__key, __address_discriminated, __discriminator) \
+ __ptrauth(__key,__address_discriminated, \
+ ptrauth_string_discriminator(__discriminator))
+// This work around is required to support divergence in spelling
+// during the ptrauth upstreaming process.
+# if __has_feature(ptrauth_restricted_intptr_qualifier)
+# define _LIBCXXABI_PTRAUTH_RESTRICTED_INTPTR(__key, __address_discriminated, \
+ __discriminator) \
+ __ptrauth_restricted_intptr(__key,__address_discriminated, \
+ ptrauth_string_discriminator(__discriminator))
+# else
+# define _LIBCXXABI_PTRAUTH_RESTRICTED_INTPTR(__key, __address_discriminated, \
+ __discriminator) \
+ __ptrauth(__key,__address_discriminated, \
+ ptrauth_string_discriminator(__discriminator))
+# endif
+#else
+# define _LIBCXXABI_PTRAUTH(__key, __address_discriminated, __discriminator)
+# define _LIBCXXABI_PTRAUTH_RESTRICTED_INTPTR(__key, __address_discriminated, \
+ __discriminator)
+#endif
+
+// Helper wrappers for pointer auth qualifiers because we use a lot of variants
+// Suffixes:
+// * _RI : qualifier is __ptrauth_restricted_intptr
+// * PDD : key is ptrauth_key_process_dependent_data
+// * FN : key is ptrauth_key_function_pointer
+#define _LIBCXXABI_PTRAUTH_PDD(__discriminator) \
+ _LIBCXXABI_PTRAUTH(ptrauth_key_process_dependent_data, \
+ /*__address_discriminated=*/1, \
+ __discriminator)
+#define _LIBCXXABI_PTRAUTH_FN(__discriminator) \
+ _LIBCXXABI_PTRAUTH(ptrauth_key_function_pointer, \
+ /*__address_discriminated=*/1, \
+ __discriminator)
+#define _LIBCXXABI_PTRAUTH_RI_PDD(__discriminator) \
+ _LIBCXXABI_PTRAUTH_RESTRICTED_INTPTR(ptrauth_key_process_dependent_data, \
+ /*__address_discriminated=*/1, \
+ __discriminator)
+
#endif // ____CXXABI_CONFIG_H
diff --git a/libcxxabi/src/cxa_exception.h b/libcxxabi/src/cxa_exception.h
index aba08f2992103..4c69d48048f02 100644
--- a/libcxxabi/src/cxa_exception.h
+++ b/libcxxabi/src/cxa_exception.h
@@ -47,10 +47,10 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {
// In Wasm, a destructor returns its argument
void *(_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
#else
- void (_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
+ void(_LIBCXXABI_DTOR_FUNC* _LIBCXXABI_PTRAUTH_FN("__cxa_exception::exceptionDestructor") exceptionDestructor)(void*);
#endif
- std::unexpected_handler unexpectedHandler;
- std::terminate_handler terminateHandler;
+ std::unexpected_handler _LIBCXXABI_PTRAUTH_FN("__cxa_exception::unexpectedHandler") unexpectedHandler;
+ std::terminate_handler _LIBCXXABI_PTRAUTH_FN("__cxa_exception::terminateHandler") terminateHandler;
__cxa_exception *nextException;
@@ -61,10 +61,10 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {
int propagationCount;
#else
int handlerSwitchValue;
- const unsigned char *actionRecord;
- const unsigned char *languageSpecificData;
- void *catchTemp;
- void *adjustedPtr;
+ const unsigned char* _LIBCXXABI_PTRAUTH_PDD("__cxa_exception::actionRecord") actionRecord;
+ const unsigned char* _LIBCXXABI_PTRAUTH_PDD("__cxa_exception::languageSpecificData") languageSpecificData;
+ void* _LIBCXXABI_PTRAUTH_PDD("__cxa_exception::catchTemp") catchTemp;
+ void* _LIBCXXABI_PTRAUTH_PDD("__cxa_exception::adjustedPtr") adjustedPtr;
#endif
#if !defined(__LP64__) && !defined(_WIN64) && !defined(_LIBCXXABI_ARM_EHABI)
@@ -79,6 +79,8 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {
// http://sourcery.mentor.com/archives/cxx-abi-dev/msg01924.html
// The layout of this structure MUST match the layout of __cxa_exception, with
// primaryException instead of referenceCount.
+// The tags used in the pointer authentication qualifiers also need to match
+// those of the corresponding members in __cxa_exception.
struct _LIBCXXABI_HIDDEN __cxa_dependent_exception {
#if defined(__LP64__) || defined(_WIN64) || defined(_LIBCXXABI_ARM_EHABI)
void* reserve; // padding.
@@ -86,9 +88,9 @@ struct _LIBCXXABI_HIDDEN __cxa_dependent_exception {
#endif
std::type_info *exceptionType;
- void (_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
- std::unexpected_handler unexpectedHandler;
- std::terminate_handler terminateHandler;
+ void(_LIBCXXABI_DTOR_FUNC* _LIBCXXABI_PTRAUTH_FN("__cxa_exception::exceptionDestructor") exceptionDestructor)(void*);
+ std::unexpected_handler _LIBCXXABI_PTRAUTH_FN("__cxa_exception::unexpectedHandler") unexpectedHandler;
+ std::terminate_handler _LIBCXXABI_PTRAUTH_FN("__cxa_exception::terminateHandler") terminateHandler;
__cxa_exception *nextException;
@@ -99,10 +101,10 @@ struct _LIBCXXABI_HIDDEN __cxa_dependent_exception {
int propagationCount;
#else
int handlerSwitchValue;
- const unsigned char *actionRecord;
- const unsigned char *languageSpecificData;
- void * catchTemp;
- void *adjustedPtr;
+ const unsigned char* _LIBCXXABI_PTRAUTH_PDD("__cxa_exception::actionRecord") actionRecord;
+ const unsigned char* _LIBCXXABI_PTRAUTH_PDD("__cxa_exception::languageSpecificData") languageSpecificData;
+ void* _LIBCXXABI_PTRAUTH_PDD("__cxa_exception::catchTemp") catchTemp;
+ void* _LIBCXXABI_PTRAUTH_PDD("__cxa_exception::adjustedPtr") adjustedPtr;
#endif
#if !defined(__LP64__) && !defined(_WIN64) && !defined(_LIBCXXABI_ARM_EHABI)
diff --git a/libcxxabi/src/cxa_personality.cpp b/libcxxabi/src/cxa_personality.cpp
index 5f6e75c5be19c..cbb3f46e0f55c 100644
--- a/libcxxabi/src/cxa_personality.cpp
+++ b/libcxxabi/src/cxa_personality.cpp
@@ -22,6 +22,12 @@
#include "private_typeinfo.h"
#include "unwind.h"
+#if __has_include(<ptrauth.h>)
+#include <ptrauth.h>
+#endif
+
+#include "libunwind.h"
+
// TODO: This is a temporary workaround for libc++abi to recognize that it's being
// built against LLVM's libunwind. LLVM's libunwind started reporting _LIBUNWIND_VERSION
// in LLVM 15 -- we can remove this workaround after shipping LLVM 17. Once we remove
@@ -527,12 +533,19 @@ get_thrown_object_ptr(_Unwind_Exception* unwind_exception)
namespace
{
+#define _LIBCXXABI_PTRAUTH_KEY ptrauth_key_process_dependent_code
+typedef const uint8_t* _LIBCXXABI_PTRAUTH_PDD("scan_results::languageSpecificData") lsd_ptr_t;
+typedef const uint8_t* _LIBCXXABI_PTRAUTH_PDD("scan_results::actionRecord") action_ptr_t;
+#define _LIBCXXABI_PTRAUTH_SCANRESULT_LANDINGPAD_DISC "scan_results::landingPad"
+typedef uintptr_t _LIBCXXABI_PTRAUTH_RI_PDD(_LIBCXXABI_PTRAUTH_SCANRESULT_LANDINGPAD_DISC) landing_pad_t;
+typedef void* _LIBCXXABI_PTRAUTH_PDD(_LIBCXXABI_PTRAUTH_SCANRESULT_LANDINGPAD_DISC) landing_pad_ptr_t;
+
struct scan_results
{
int64_t ttypeIndex; // > 0 catch handler, < 0 exception spec handler, == 0 a cleanup
- const uint8_t* actionRecord; // Currently unused. Retained to ease future maintenance.
- const uint8_t* languageSpecificData; // Needed only for __cxa_call_unexpected
- uintptr_t landingPad; // null -> nothing found, else something found
+ action_ptr_t actionRecord; // Currently unused. Retained to ease future maintenance.
+ lsd_ptr_t languageSpecificData; // Needed only for __cxa_call_unexpected
+ landing_pad_t landingPad; // null -> nothing found, else something found
void* adjustedPtr; // Used in cxa_exception.cpp
_Unwind_Reason_Code reason; // One of _URC_FATAL_PHASE1_ERROR,
// _URC_FATAL_PHASE2_ERROR,
@@ -541,7 +554,33 @@ struct scan_results
};
} // unnamed namespace
+}
+namespace {
+// The logical model for casting authenticated function pointers makes
+// it impossible to directly cast them without breaking the authentication,
+// as a result we need this pair of helpers.
+template <typename PtrType>
+void set_landing_pad_as_ptr(scan_results& results, const PtrType& out) {
+ union {
+ landing_pad_t* as_landing_pad;
+ landing_pad_ptr_t* as_pointer;
+ } u;
+ u.as_landing_pad = &results.landingPad;
+ *u.as_pointer = out;
+}
+
+static const landing_pad_ptr_t& get_landing_pad_as_ptr(const scan_results& results) {
+ union {
+ const landing_pad_t* as_landing_pad;
+ const landing_pad_ptr_t* as_pointer;
+ } u;
+ u.as_landing_pad = &results.landingPad;
+ return *u.as_pointer;
+}
+} // unnamed namespace
+
+extern "C" {
static
void
set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context,
@@ -557,7 +596,22 @@ set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context,
reinterpret_cast<uintptr_t>(unwind_exception));
_Unwind_SetGR(context, __builtin_eh_return_data_regno(1),
static_cast<uintptr_t>(results.ttypeIndex));
+#if defined(__APPLE__) && __has_feature(ptrauth_qualifier)
+ auto stack_pointer = _Unwind_GetGR(context, UNW_REG_SP);
+ // We manually re-sign the IP as the __ptrauth qualifiers cannot
+ // express the required relationship with the destination address
+ const auto existingDiscriminator = ptrauth_blend_discriminator(
+ &results.landingPad,
+ ptrauth_string_discriminator(_LIBCXXABI_PTRAUTH_SCANRESULT_LANDINGPAD_DISC));
+ unw_word_t newIP = (unw_word_t)ptrauth_auth_and_resign(*(void**)&results.landingPad,
+ _LIBCXXABI_PTRAUTH_KEY,
+ existingDiscriminator,
+ ptrauth_key_return_address,
+ stack_pointer);
+ _Unwind_SetIP(context, newIP);
+#else
_Unwind_SetIP(context, results.landingPad);
+#endif
}
/*
@@ -691,12 +745,12 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
// The call sites are ordered in increasing value of start
uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding);
uintptr_t length = readEncodedPointer(&callSitePtr, callSiteEncoding);
- uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding);
+ landing_pad_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding);
uintptr_t actionEntry = readULEB128(&callSitePtr);
if ((start <= ipOffset) && (ipOffset < (start + length)))
#else // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__
// ip is 1-based index into this table
- uintptr_t landingPad = readULEB128(&callSitePtr);
+ landing_pad_t landingPad = readULEB128(&callSitePtr);
uintptr_t actionEntry = readULEB128(&callSitePtr);
if (--ip == 0)
#endif // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__
@@ -935,8 +989,7 @@ __gxx_personality_v0
results.ttypeIndex = exception_header->handlerSwitchValue;
results.actionRecord = exception_header->actionRecord;
results.languageSpecificData = exception_header->languageSpecificData;
- results.landingPad =
- reinterpret_cast<uintptr_t>(exception_header->catchTemp);
+ set_landing_pad_as_ptr(results, exception_header->catchTemp);
results.adjustedPtr = exception_header->adjustedPtr;
// Jump to the handler.
@@ -970,7 +1023,7 @@ __gxx_personality_v0
exc->handlerSwitchValue = static_cast<int>(results.ttypeIndex);
exc->actionRecord = results.actionRecord;
exc->languageSpecificData = results.languageSpecificData;
- exc->catchTemp = reinterpret_cast<void*>(results.landingPad);
+ exc->catchTemp = get_landing_pad_as_ptr(results);
exc->adjustedPtr = results.adjustedPtr;
#ifdef __WASM_EXCEPTIONS__
// Wasm only uses a single phase (_UA_SEARCH_PHASE), so save the
diff --git a/libunwind/include/libunwind.h b/libunwind/include/libunwind.h
index b2dae8feed9a3..e7375bbca1b3d 100644
--- a/libunwind/include/libunwind.h
+++ b/libunwind/include/libunwind.h
@@ -43,6 +43,61 @@
#define LIBUNWIND_AVAIL
#endif
+#if __has_include(<ptrauth.h>)
+#include <ptrauth.h>
+#endif
+
+#if defined(__APPLE__) && __has_feature(ptrauth_qualifier)
+#define _LIBUNWIND_PTRAUTH(__key, __address_discriminated, __discriminator) \
+ __ptrauth(__key, __address_discriminated, \
+ ptrauth_string_discriminator(__discriminator))
+// This work around is required to support divergence in spelling
+// developed during the ptrauth upstreaming process.
+#if __has_feature(ptrauth_restricted_intptr_qualifier)
+#define _LIBUNWIND_PTRAUTH_RESTRICTED_INTPTR(__key, __address_discriminated, \
+ __discriminator) \
+ __ptrauth_restricted_intptr(__key, __address_discriminated, \
+ ptrauth_string_discriminator(__discriminator...
[truncated]
|
You can test this locally with the following command:git-clang-format --diff origin/main HEAD --extensions h,c,hpp,cpp -- compiler-rt/lib/builtins/gcc_personality_v0.c libcxxabi/include/__cxxabi_config.h libcxxabi/src/cxa_exception.cpp libcxxabi/src/cxa_exception.h libcxxabi/src/cxa_personality.cpp libunwind/include/__libunwind_config.h libunwind/include/libunwind.h libunwind/src/AddressSpace.hpp libunwind/src/CompactUnwinder.hpp libunwind/src/DwarfInstructions.hpp libunwind/src/DwarfParser.hpp libunwind/src/Registers.hpp libunwind/src/UnwindCursor.hpp libunwind/src/UnwindLevel1.c libunwind/src/libunwind.cpp
View the diff from clang-format here.diff --git a/libcxxabi/src/cxa_exception.h b/libcxxabi/src/cxa_exception.h
index 2eb77d861..aa8969e59 100644
--- a/libcxxabi/src/cxa_exception.h
+++ b/libcxxabi/src/cxa_exception.h
@@ -47,7 +47,7 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {
// In Wasm, a destructor returns its argument
void *(_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
#else
- void (_LIBCXXABI_DTOR_FUNC *__ptrauth_cxxabi_exception_destructor exceptionDestructor)(void *);
+ void(_LIBCXXABI_DTOR_FUNC* __ptrauth_cxxabi_exception_destructor exceptionDestructor)(void*);
#endif
std::unexpected_handler __ptrauth_cxxabi_unexpected_handler unexpectedHandler;
std::terminate_handler __ptrauth_cxxabi_terminate_handler terminateHandler;
@@ -61,10 +61,10 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {
int propagationCount;
#else
int handlerSwitchValue;
- const unsigned char *__ptrauth_cxxabi_action_record actionRecord;
- const unsigned char *__ptrauth_cxxabi_lsd languageSpecificData;
- void *__ptrauth_cxxabi_catch_temp catchTemp;
- void *__ptrauth_cxxabi_adjusted_ptr adjustedPtr;
+ const unsigned char* __ptrauth_cxxabi_action_record actionRecord;
+ const unsigned char* __ptrauth_cxxabi_lsd languageSpecificData;
+ void* __ptrauth_cxxabi_catch_temp catchTemp;
+ void* __ptrauth_cxxabi_adjusted_ptr adjustedPtr;
#endif
#if !defined(__LP64__) && !defined(_WIN64) && !defined(_LIBCXXABI_ARM_EHABI)
@@ -88,7 +88,7 @@ struct _LIBCXXABI_HIDDEN __cxa_dependent_exception {
#endif
std::type_info *exceptionType;
- void (_LIBCXXABI_DTOR_FUNC *__ptrauth_cxxabi_exception_destructor exceptionDestructor)(void *);
+ void(_LIBCXXABI_DTOR_FUNC* __ptrauth_cxxabi_exception_destructor exceptionDestructor)(void*);
std::unexpected_handler __ptrauth_cxxabi_unexpected_handler unexpectedHandler;
std::terminate_handler __ptrauth_cxxabi_terminate_handler terminateHandler;
@@ -102,10 +102,10 @@ struct _LIBCXXABI_HIDDEN __cxa_dependent_exception {
#else
int handlerSwitchValue;
- const unsigned char *__ptrauth_cxxabi_action_record actionRecord;
- const unsigned char *__ptrauth_cxxabi_lsd languageSpecificData;
- void *__ptrauth_cxxabi_catch_temp catchTemp;
- void *__ptrauth_cxxabi_adjusted_ptr adjustedPtr;
+ const unsigned char* __ptrauth_cxxabi_action_record actionRecord;
+ const unsigned char* __ptrauth_cxxabi_lsd languageSpecificData;
+ void* __ptrauth_cxxabi_catch_temp catchTemp;
+ void* __ptrauth_cxxabi_adjusted_ptr adjustedPtr;
#endif
#if !defined(__LP64__) && !defined(_WIN64) && !defined(_LIBCXXABI_ARM_EHABI)
diff --git a/libcxxabi/src/cxa_personality.cpp b/libcxxabi/src/cxa_personality.cpp
index 14e6f4b07..16b424901 100644
--- a/libcxxabi/src/cxa_personality.cpp
+++ b/libcxxabi/src/cxa_personality.cpp
@@ -564,10 +564,10 @@ get_thrown_object_ptr(_Unwind_Exception* unwind_exception)
namespace
{
-typedef const uint8_t *__ptrauth_scan_results_lsd lsd_ptr_t;
-typedef const uint8_t *__ptrauth_scan_results_action_record action_ptr_t;
+typedef const uint8_t* __ptrauth_scan_results_lsd lsd_ptr_t;
+typedef const uint8_t* __ptrauth_scan_results_action_record action_ptr_t;
typedef uintptr_t __ptrauth_scan_results_landingpad_intptr landing_pad_t;
-typedef void *__ptrauth_scan_results_landingpad landing_pad_ptr_t;
+typedef void* __ptrauth_scan_results_landingpad landing_pad_ptr_t;
struct scan_results
{
diff --git a/libunwind/include/__libunwind_config.h b/libunwind/include/__libunwind_config.h
index 1e5232392..9122243ac 100644
--- a/libunwind/include/__libunwind_config.h
+++ b/libunwind/include/__libunwind_config.h
@@ -73,11 +73,12 @@
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC
# elif defined(__aarch64__)
# define _LIBUNWIND_TARGET_AARCH64 1
-# if __has_feature(ptrauth_calls) && __has_feature(ptrauth_returns)
-# define _LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING 1
-# elif __has_feature(ptrauth_calls) != __has_feature(ptrauth_returns)
-# #error "Either both or none of ptrauth_calls and ptrauth_returns is allowed to be enabled"
-# endif
+#if __has_feature(ptrauth_calls) && __has_feature(ptrauth_returns)
+#define _LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING 1
+#elif __has_feature(ptrauth_calls) != __has_feature(ptrauth_returns)
+# #error \
+ "Either both or none of ptrauth_calls and ptrauth_returns is allowed to be enabled"
+#endif
#define _LIBUNWIND_CONTEXT_SIZE 67
# if defined(__SEH__)
# define _LIBUNWIND_CURSOR_SIZE 164
diff --git a/libunwind/include/libunwind.h b/libunwind/include/libunwind.h
index 5d5b583bb..c44bf3435 100644
--- a/libunwind/include/libunwind.h
+++ b/libunwind/include/libunwind.h
@@ -45,100 +45,115 @@
#if __has_feature(ptrauth_calls)
- #include <ptrauth.h>
+#include <ptrauth.h>
- #if __has_extension(ptrauth_restricted_intptr_qualifier)
- #define __unwind_ptrauth_restricted_intptr(...) \
- __ptrauth_restricted_intptr(__VA_ARGS__)
- #else
- #define __unwind_ptrauth_restricted_intptr(...) \
- __ptrauth(__VA_ARGS__)
- #endif
+#if __has_extension(ptrauth_restricted_intptr_qualifier)
+#define __unwind_ptrauth_restricted_intptr(...) \
+ __ptrauth_restricted_intptr(__VA_ARGS__)
+#else
+#define __unwind_ptrauth_restricted_intptr(...) __ptrauth(__VA_ARGS__)
+#endif
// ptrauth_string_discriminator("unw_proc_info_t::handler") == 0x7405
- #define __ptrauth_unwind_upi_handler_disc 0x7405
+#define __ptrauth_unwind_upi_handler_disc 0x7405
- #define __ptrauth_unwind_upi_handler \
- __ptrauth(ptrauth_key_function_pointer, 1, __ptrauth_unwind_upi_handler_disc)
+#define __ptrauth_unwind_upi_handler \
+ __ptrauth(ptrauth_key_function_pointer, 1, __ptrauth_unwind_upi_handler_disc)
- #define __ptrauth_unwind_upi_handler_intptr \
- __unwind_ptrauth_restricted_intptr(ptrauth_key_function_pointer, 1,\
- __ptrauth_unwind_upi_handler_disc)
+#define __ptrauth_unwind_upi_handler_intptr \
+ __unwind_ptrauth_restricted_intptr(ptrauth_key_function_pointer, 1, \
+ __ptrauth_unwind_upi_handler_disc)
// ptrauth_string_discriminator("unw_proc_info_t::start_ip") == 0xCA2C
- #define __ptrauth_unwind_upi_startip \
- __unwind_ptrauth_restricted_intptr(ptrauth_key_process_independent_code, 1, 0xCA2C)
+#define __ptrauth_unwind_upi_startip \
+ __unwind_ptrauth_restricted_intptr(ptrauth_key_process_independent_code, 1, \
+ 0xCA2C)
// ptrauth_string_discriminator("unw_proc_info_t::end_ip") == 0xE183
- #define __ptrauth_unwind_upi_endip \
- __unwind_ptrauth_restricted_intptr(ptrauth_key_process_independent_code, 1, 0xE183)
+#define __ptrauth_unwind_upi_endip \
+ __unwind_ptrauth_restricted_intptr(ptrauth_key_process_independent_code, 1, \
+ 0xE183)
// ptrauth_string_discriminator("unw_proc_info_t::lsda") == 0x83DE
- #define __ptrauth_unwind_upi_lsda \
- __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x83DE)
+#define __ptrauth_unwind_upi_lsda \
+ __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, \
+ 0x83DE)
// ptrauth_string_discriminator("unw_proc_info_t::flags") == 0x79A1
- #define __ptrauth_unwind_upi_flags \
- __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x79A1)
+#define __ptrauth_unwind_upi_flags \
+ __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, \
+ 0x79A1)
// ptrauth_string_discriminator("unw_proc_info_t::unwind_info") == 0xC20C
- #define __ptrauth_unwind_upi_info \
- __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0xC20C)
+#define __ptrauth_unwind_upi_info \
+ __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, \
+ 0xC20C)
// ptrauth_string_discriminator("unw_proc_info_t::extra") == 0x03DF
- #define __ptrauth_unwind_upi_extra \
- __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x03DF)
+#define __ptrauth_unwind_upi_extra \
+ __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, \
+ 0x03DF)
// ptrauth_string_discriminator("Registers_arm64::link_reg_t") == 0x8301
- #define __ptrauth_unwind_registers_arm64_link_reg \
- __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_code, 1, 0x8301)
+#define __ptrauth_unwind_registers_arm64_link_reg \
+ __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_code, 1, \
+ 0x8301)
// ptrauth_string_discriminator("UnwindInfoSections::dso_base") == 0x4FF5
- #define __ptrauth_unwind_uis_dso_base \
- __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x4FF5)
+#define __ptrauth_unwind_uis_dso_base \
+ __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, \
+ 0x4FF5)
// ptrauth_string_discriminator("UnwindInfoSections::dwarf_section") == 0x4974
- #define __ptrauth_unwind_uis_dwarf_section \
- __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x4974)
+#define __ptrauth_unwind_uis_dwarf_section \
+ __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, \
+ 0x4974)
-// ptrauth_string_discriminator("UnwindInfoSections::dwarf_section_length") == 0x2A9A
- #define __ptrauth_unwind_uis_dwarf_section_length \
- __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x2A9A)
+// ptrauth_string_discriminator("UnwindInfoSections::dwarf_section_length") ==
+// 0x2A9A
+#define __ptrauth_unwind_uis_dwarf_section_length \
+ __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, \
+ 0x2A9A)
-// ptrauth_string_discriminator("UnwindInfoSections::compact_unwind_section") == 0xA27B
- #define __ptrauth_unwind_uis_compact_unwind_section \
- __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0xA27B)
+// ptrauth_string_discriminator("UnwindInfoSections::compact_unwind_section") ==
+// 0xA27B
+#define __ptrauth_unwind_uis_compact_unwind_section \
+ __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, \
+ 0xA27B)
-// ptrauth_string_discriminator("UnwindInfoSections::compact_unwind_section_length") == 0x5D0A
- #define __ptrauth_unwind_uis_compact_unwind_section_length \
- __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x5D0A)
+// ptrauth_string_discriminator("UnwindInfoSections::compact_unwind_section_length")
+// == 0x5D0A
+#define __ptrauth_unwind_uis_compact_unwind_section_length \
+ __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, \
+ 0x5D0A)
// ptrauth_string_discriminator("CIE_Info::personality") == 0x6A40
- #define __ptrauth_unwind_cie_info_personality_disc 0x6A40
- #define __ptrauth_unwind_cie_info_personality \
- __unwind_ptrauth_restricted_intptr(ptrauth_key_function_pointer, 1, \
- __ptrauth_unwind_cie_info_personality_disc)
+#define __ptrauth_unwind_cie_info_personality_disc 0x6A40
+#define __ptrauth_unwind_cie_info_personality \
+ __unwind_ptrauth_restricted_intptr( \
+ ptrauth_key_function_pointer, 1, \
+ __ptrauth_unwind_cie_info_personality_disc)
// ptrauth_string_discriminator("personality") == 0x7EAD)
- #define __ptrauth_unwind_pacret_personality_disc 0x7EAD
+#define __ptrauth_unwind_pacret_personality_disc 0x7EAD
#else
- #define __ptrauth_unwind_upi_handler
- #define __ptrauth_unwind_upi_handler_intptr
- #define __ptrauth_unwind_upi_startip
- #define __ptrauth_unwind_upi_endip
- #define __ptrauth_unwind_upi_lsda
- #define __ptrauth_unwind_upi_flags
- #define __ptrauth_unwind_upi_info
- #define __ptrauth_unwind_upi_extra
- #define __ptrauth_unwind_registers_arm64_link_reg
- #define __ptrauth_unwind_uis_dso_base
- #define __ptrauth_unwind_uis_dwarf_section
- #define __ptrauth_unwind_uis_dwarf_section_length
- #define __ptrauth_unwind_uis_compact_unwind_section
- #define __ptrauth_unwind_uis_compact_unwind_section_length
- #define __ptrauth_unwind_cie_info_personality
+#define __ptrauth_unwind_upi_handler
+#define __ptrauth_unwind_upi_handler_intptr
+#define __ptrauth_unwind_upi_startip
+#define __ptrauth_unwind_upi_endip
+#define __ptrauth_unwind_upi_lsda
+#define __ptrauth_unwind_upi_flags
+#define __ptrauth_unwind_upi_info
+#define __ptrauth_unwind_upi_extra
+#define __ptrauth_unwind_registers_arm64_link_reg
+#define __ptrauth_unwind_uis_dso_base
+#define __ptrauth_unwind_uis_dwarf_section
+#define __ptrauth_unwind_uis_dwarf_section_length
+#define __ptrauth_unwind_uis_compact_unwind_section
+#define __ptrauth_unwind_uis_compact_unwind_section_length
+#define __ptrauth_unwind_cie_info_personality
#endif
#if defined(_WIN32) && defined(__SEH__)
@@ -186,18 +201,23 @@ typedef double unw_fpreg_t;
#endif
struct unw_proc_info_t {
- unw_word_t __ptrauth_unwind_upi_startip start_ip; /* start address of function */
- unw_word_t __ptrauth_unwind_upi_endip end_ip; /* address after end of function */
- unw_word_t __ptrauth_unwind_upi_lsda lsda; /* address of language specific data area, */
- /* or zero if not used */
+ unw_word_t __ptrauth_unwind_upi_startip
+ start_ip; /* start address of function */
+ unw_word_t __ptrauth_unwind_upi_endip
+ end_ip; /* address after end of function */
+ unw_word_t __ptrauth_unwind_upi_lsda
+ lsda; /* address of language specific data area, */
+ /* or zero if not used */
unw_word_t __ptrauth_unwind_upi_handler_intptr handler;
- unw_word_t gp; /* not used */
- unw_word_t __ptrauth_unwind_upi_flags flags; /* not used */
- uint32_t format; /* compact unwind encoding, or zero if none */
- uint32_t unwind_info_size; /* size of DWARF unwind info, or zero if none */
- unw_word_t __ptrauth_unwind_upi_info unwind_info; /* address of DWARF unwind info, or zero */
- unw_word_t __ptrauth_unwind_upi_extra extra; /* mach_header of mach-o image containing func */
+ unw_word_t gp; /* not used */
+ unw_word_t __ptrauth_unwind_upi_flags flags; /* not used */
+ uint32_t format; /* compact unwind encoding, or zero if none */
+ uint32_t unwind_info_size; /* size of DWARF unwind info, or zero if none */
+ unw_word_t __ptrauth_unwind_upi_info
+ unwind_info; /* address of DWARF unwind info, or zero */
+ unw_word_t __ptrauth_unwind_upi_extra
+ extra; /* mach_header of mach-o image containing func */
};
typedef struct unw_proc_info_t unw_proc_info_t;
diff --git a/libunwind/src/AddressSpace.hpp b/libunwind/src/AddressSpace.hpp
index 63f9cb367..f38dda47c 100644
--- a/libunwind/src/AddressSpace.hpp
+++ b/libunwind/src/AddressSpace.hpp
@@ -129,27 +129,24 @@ struct UnwindInfoSections {
defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) || \
defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
// No dso_base for SEH.
- uintptr_t __ptrauth_unwind_uis_dso_base
- dso_base = 0;
+ uintptr_t __ptrauth_unwind_uis_dso_base dso_base = 0;
#endif
#if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
size_t text_segment_length;
#endif
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
- uintptr_t __ptrauth_unwind_uis_dwarf_section
- dwarf_section = 0;
- size_t __ptrauth_unwind_uis_dwarf_section_length
- dwarf_section_length = 0;
+ uintptr_t __ptrauth_unwind_uis_dwarf_section dwarf_section = 0;
+ size_t __ptrauth_unwind_uis_dwarf_section_length dwarf_section_length = 0;
#endif
#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
uintptr_t dwarf_index_section;
size_t dwarf_index_section_length;
#endif
#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
- uintptr_t __ptrauth_unwind_uis_compact_unwind_section
- compact_unwind_section = 0;
+ uintptr_t __ptrauth_unwind_uis_compact_unwind_section compact_unwind_section =
+ 0;
size_t __ptrauth_unwind_uis_compact_unwind_section_length
- compact_unwind_section_length = 0;
+ compact_unwind_section_length = 0;
#endif
#if defined(_LIBUNWIND_ARM_EHABI)
uintptr_t arm_section;
diff --git a/libunwind/src/DwarfInstructions.hpp b/libunwind/src/DwarfInstructions.hpp
index d9fa76c57..d2822e8be 100644
--- a/libunwind/src/DwarfInstructions.hpp
+++ b/libunwind/src/DwarfInstructions.hpp
@@ -302,7 +302,7 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace,
isSignalFrame = cieInfo.isSignalFrame;
-#if defined(_LIBUNWIND_TARGET_AARCH64) && \
+#if defined(_LIBUNWIND_TARGET_AARCH64) && \
!defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
// There are two ways of return address signing: pac-ret (enabled via
// -mbranch-protection=pac-ret) and ptrauth-returns (enabled as part of
diff --git a/libunwind/src/DwarfParser.hpp b/libunwind/src/DwarfParser.hpp
index cca3ae0cc..56b4b35b3 100644
--- a/libunwind/src/DwarfParser.hpp
+++ b/libunwind/src/DwarfParser.hpp
@@ -325,7 +325,7 @@ template <typename CIE_Info, typename T>
memmove((void *)&info->personality, (void *)&signed_personality,
sizeof(signed_personality));
}
-}
+} // namespace
/// Extract info from a CIE
template <typename A>
diff --git a/libunwind/src/Registers.hpp b/libunwind/src/Registers.hpp
index adbab6687..4ed1db540 100644
--- a/libunwind/src/Registers.hpp
+++ b/libunwind/src/Registers.hpp
@@ -1863,29 +1863,25 @@ public:
uint64_t getSP() const { return _registers.__sp; }
void setSP(uint64_t value) { _registers.__sp = value; }
- uint64_t getIP() const {
+ uint64_t getIP() const {
uint64_t value = _registers.__pc;
#if __has_feature(ptrauth_calls)
// Note the value of the PC was signed to its address in the register state
// but everyone else expects it to be sign by the SP, so convert on return.
- value = (uint64_t)ptrauth_auth_and_resign((void *)_registers.__pc,
- ptrauth_key_return_address,
- &_registers.__pc,
- ptrauth_key_return_address,
- getSP());
+ value = (uint64_t)ptrauth_auth_and_resign(
+ (void *)_registers.__pc, ptrauth_key_return_address, &_registers.__pc,
+ ptrauth_key_return_address, getSP());
#endif
return value;
}
- void setIP(uint64_t value) {
+ void setIP(uint64_t value) {
#if __has_feature(ptrauth_calls)
// Note the value which was set should have been signed with the SP.
// We then resign with the slot we are being stored in to so that both SP
// and LR can't be spoofed at the same time.
- value = (uint64_t)ptrauth_auth_and_resign((void *)value,
- ptrauth_key_return_address,
- getSP(),
- ptrauth_key_return_address,
- &_registers.__pc);
+ value = (uint64_t)ptrauth_auth_and_resign(
+ (void *)value, ptrauth_key_return_address, getSP(),
+ ptrauth_key_return_address, &_registers.__pc);
#endif
_registers.__pc = value;
}
@@ -1898,10 +1894,9 @@ public:
link_reg_t *referenceAuthedLinkRegister) {
// If we are in an arm64/arm64e frame, then the PC should have been signed
// with the SP
- *referenceAuthedLinkRegister =
- (uint64_t)ptrauth_auth_data((void *)inplaceAuthedLinkRegister,
- ptrauth_key_return_address,
- _registers.__sp);
+ *referenceAuthedLinkRegister = (uint64_t)ptrauth_auth_data(
+ (void *)inplaceAuthedLinkRegister, ptrauth_key_return_address,
+ _registers.__sp);
}
#endif
|
6810396
to
637245f
Compare
@kovdan01 @atrosinenko Please take a look |
Updating formatting before review - had discussed with Louis and he expressed a preference for some of it, but this llvm.org style bot complains many other cases (likely a local config issue when I was trying to cleanup the downstream code. So I've updated with a direct clang-format fix. |
unused variable errors are likely fallout from refactoring and workaround removals I did as part of the prep, will do some cleanup/diagnostics work later this week. I mostly wanted to get this available to others to see whether they were ok adopting this rather than rolling their own version. |
@ojhunt JFYI: I've published a couple of small fixes I've applied locally at https://github.com/kovdan01/llvm-project/commits/pointer-authenticated-unwinding-fix0/. Maybe this would be useful |
I'd posted this to try and avoid too much duplicated work so it's highly possible some of these issues are due to me screwing up refactoring, cleanups, or the patch preparation. I'll get back to this after wg21 wraps up this week, so sorry for the delays. |
I'll be back to working on this later today - there's a pile of feedback, and a bunch of nonsense that I managed to accidentally accrue and/or re-format when pushing the PR so it will take a little time to unbreak that. It may be easiest to force push a repaired PR first and then address comments. I also realize that some of the breakage might be due to mismatched APPLE vs has_feature(actual_feature) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have tested this patch on Linux with aarch64-linux-pauthtest
triple and custom-built sysroot, here are the results.
In my setup, the tests pass on the following modified branch: https://github.com/atrosinenko/llvm-project/commits/pointer-authenticated-unwinding-fix1/. It is based on https://github.com/kovdan01/llvm-project/commits/pointer-authenticated-unwinding-fix0/ with the following changes:
- Currently, several parts of the patch are only enabled on Apple targets. For testing purposes, I unconditionally enabled parts of this patch guarded by
defined(__APPLE__)
. - It turned out that
__has_feature(ptrauth_qualifier)
does not work in mainline, so I replaced it with__has_feature(ptrauth_intrinsics)
. I expect the correct solution proposed by @kovdan01 (replacing with__has_extension(ptrauth_qualifier)
) to behave identically. - The change to
compiler-rt/lib/profile/InstrProfilingValue.c
seems to be unrelated to libunwind - The most meaningful change is updating signing schemas is several places - see inline comments. Additionally, I had to update a few other places that I cannot add inline comments to
- in
Registers_arm64::getRegister
andRegisters_arm64::setRegister
, replace direct references to_registers.__pc
with calls togetIP()
andsetIP()
, correspondingly - disable the existing pauth-related logic in
DwarfInstructions<A, R>::stepWithDwarf
- in
The fact I'm worried about is whether implicit signing and authentication on accesses to __ptrauth
-qualified fields may introduce signing or authentication oracles usable by an attacker, since many values stored to these fields are initially non-signed. This is possibly mitigated by the fact that all these fields use address diversity with distinct integer discriminators and/or the original values are taken from read-only memory. On the other hand, discriminator computation, auth / sign intrinsic and load / store to memory are currently three separate operations when accessing a __ptrauth
-qualified field, thus spilling of intermediate values to the stack is possible. Furthermore, even if the non-signed value originates from a read-only memory, this is not expressed in LLVM IR terms, thus the optimization pipeline may transform sensitive instruction sequences in an unsafe way.
@ojhunt I closed all the threads which are no longer relevant or are duplicates. Now we have only 5 non-trivial and 5 trivial issues which really need to be resolved before merging the PR. All other enhancements could be done as follow-up patches. I've created pointer-authenticated-unwinding-2025-09-22-with-fixes in my fork containing fixes for all the non-trivial issues listed below. Commit links are provided in the list below and in corresponding threads. Please let me know if you have any questions or any help is needed regarding this. To be done in scope of this PRTrivial formatting issuesThese require almost zero effort to apply. Please consider fixing these first so we do not need to worry about them anymore.
Non-trivial styling-related issues
An issue causing a runtime crashDo not mix pac-ret and ptrauth_returns. See thread https://github.com/llvm/llvm-project/pull/143230/files#r2369419226 and commit ced8b99. Other non-trivial issuesVerify FP is handled correctly https://github.com/llvm/llvm-project/pull/143230/files#r2369428305 To be done as a follow-up
|
1e5b4cb
to
5f5f75e
Compare
This hardens the unwinding logic and datastructures on systems that support pointer authentication. The approach taken to hardening is to harden the schemas of as many high value fields in the myriad structs as possible, and then also explicitly qualify local variables referencing privileged or security critical values. This does introduce ABI linkage between libcxx, libcxxabi, and libunwind but those are in principle separate from the OS itself so we've kept the schema definitions in the library specific headers rather than ptrauth.h
At some point I lost the changes to loadAndAuthenticateLinkRegister I also updated schema names in libunwind to be more consistent Finally while looking at the total diff I saw some places that the formatting could be improved.
5f5f75e
to
ad625da
Compare
Had to rebase as there was a divergence between my tree and this one - possibly I accidentally merged main to the PR |
👍
Done
That would mean that apple clang will not be able to build the runtimes. That's not a real option.
I've moved this behind a matching #define of the code that calls them, I'm trying to work out if there is a real reason for the functions being separated from their usage as much as they are.
Fixed with an arm64e guard.
It is, I've fixed the misleading - we were experimenting with signed frame pointers for a while.
Pinged Ahmed on this one, I don't know the full impact of that change My preference would be to remove those from release builds entirely and replace LIBUNWIND_ABORT() with explicit immediate traps. This is possibly difficult. The functional ABI implication of most of these is purely between libcxx and libcxxabi, and our platform model does not support updating/changing those separately, which means we think we might be able to change/improve some of the aspects in future. Moving them to this is the "personality" discriminated one right? I think I already incorporated it into the latest revision. |
Sigh, built wrong repo, basic errors which I'm fixing now |
T signed_personality) { | ||
static_assert(sizeof(info->personality) == sizeof(signed_personality), | ||
"Signed personality is the wrong size"); | ||
memmove((void *)&info->personality, (void *)&signed_personality, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: I guess we can just use memcpy
since memmove
has additional overhead of handling overlapping memory regions. Here, signed_personality
is a local variable, so we can guarantee that there is no overlapping.
Also, it's probably worth explicitly including <string.h>
(well, <cstring>
should be better for C++ headers, but we already have includes for C-style headers, so let's stick with existing conventions)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, other platforms haven't simply adopted the "handle overlap correctly everywhere" approach? :-/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, other platforms haven't simply adopted the "handle overlap correctly everywhere" approach? :-/
@ojhunt I honestly can't say for all the platforms, but I suppose that memcpy
expresses the intention better than memmove
here
@ojhunt Thanks for an update! I've resolved several threads, but some things should still be fixed. Please let me know if you have any comments/questions or any help is needed from my side. Trivial style-related issuesThese require almost zero effort to apply. Please consider fixing these first so we do not need to worry about them anymore.
Non-trivial styling-related issuesRefactor preprocessor checks against ptrauth. See thread #143230 (comment) and proposed fix 644405b Breaking change to be reverted
This does not seem to fix the originally described issue, moreover, it looks like this breaks previously working behavior. See #143230 (comment). |
I think fixed?
That sounds ok
Minor detail :D I think fixed correctly now (based on what you posted) but I need to verify the correct thing happens on arm64e (this will take a few days). There's still the ifdef'd definition of the helper function in the current version, but I'll move that around in a bit. |
__ptrauth_unwind_cie_info_personality_disc) | ||
|
||
// ptrauth_string_discriminator("personality") == 0x7EAD) | ||
#define __ptrauth_unwind_pacret_personality_disc 0x7EAD |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose the name is a bit misleading. Let's use smth like the following:
#define __ptrauth_unwind_pacret_personality_disc 0x7EAD | |
#define __ptrauth_unwind_pauthtest_personality_disc 0x7EAD |
// __ptrauth_nop_cast cannot be used here as the authentication schemas include | ||
// address diversification. | ||
template <typename PtrType> | ||
void set_landing_pad_as_ptr(scan_results& results, const PtrType& out) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll open a "placeholder" thread just as a reminder that we need to get #161027 with additional macros merged first, and make use of those macros instead of these functions.
_Unwind_Personality_Fn __ptrauth_unwind_upi_handler *handler; | ||
} u; | ||
u.opaque_handler = (void *)&frameInfo->handler; | ||
return *u.handler; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While this should be valid in C, in C++ reading from the member of the union that wasn't most recently written is technically UB: https://en.cppreference.com/w/cpp/language/union.html.
I think we need to conform to C++ standard and use smth like memcpy
for doing such a trick.
|
||
#include <ptrauth.h> | ||
|
||
#if __has_extension(ptrauth_restricted_intptr_qualifier) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add a comment explaining that we need that because of Apple's fork so people unaware of the problem would know why such checks are needed.
The comment might look like this:
// In Apple's fork of clang, `__ptrauth` qualifier can be only applied to
// pointer types, and `__ptrauth_restricted_intptr` is used instead for
// integer types. In mainline clang, we only have `__ptrauth` which could
// be applied both to pointer and integer types.
// These helper macros allow seemless build of runtime libraries with
// Apple's fork of clang.
// TODO: If/when Apple's clang switches to mainline way of using
// `__ptrauth` qualifier, get rid of these conditionals.
unw_word_t result; | ||
__unw_get_reg(cursor, UNW_REG_IP, &result); | ||
|
||
#if defined(__ARM64E__) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like you've accidentally changes this from a generic check against ptrauth being enabled to a check against arm64e. To make tests passing on Linux, we need to use smth like _LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING
.
@ojhunt Thanks for an update! With the latest fixes, we only have one trivial issue which prevents Linux tests from passing (and I believe that it was introduced accidentally and it looks like that we need literally zero effort to fix that). With that being fixed, tests are passing on Linux in the following configurations:
Besides that, there are several other small issues here and there. See the list below. Please let me know if any help with fixing these issues is needed - I would be glad to provide any support.
(The issues below could be resolved in follow-up PRs, keeping description here not to lose them)
Looking forward for further updates and hope that this could be finally merged relatively soon :) |
This hardens the unwinding logic and datastructures on systems
that support pointer authentication.
The approach taken to hardening is to harden the schemas of as many
high value fields in the myriad structs as possible, and then also
explicitly qualify local variables referencing privileged or security
critical values.
This does introduce ABI linkage between libcxx, libcxxabi, and
libunwind but those are in principle separate from the OS itself
so we've kept the schema definitions in the library specific headers
rather than ptrauth.h